// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.

#ifndef RIOT_CORE_H_
#define RIOT_CORE_H_

#include <stdint.h>
#include <stddef.h>
#include "status/rot_status.h"
#include "crypto/x509.h"


void riot_core_clear (void *data, size_t length);


/**
 * The interface to execute RIoT Core functionality.
 */
struct riot_core {
	/**
	 * Generate the Device ID key from the CDI.
	 *
	 * Once this operation has completed, the CDI is no longer necessary and doesn't need to be
	 * maintained by the calling application.  However, in order to accommodate any situation with
	 * respect to storage of the CDI, the value of the CDI is not cleared by the RIoT Core.  THE
	 * CALLING APPLICATION MUST BE SURE THE CDI VALUE IS WIPED OUT PRIOR TO STARTING THE NEXT
	 * APPLICATION STAGE.
	 *
	 * @param riot The RIoT Core instance.
	 * @param cdi The CDI for the device.  No validation will be done against this pointer, since
	 * where the CDI is stored is platform defined.  The platform may choose to put the CDI in
	 * memory locations that are typically invalid, such as address 0.
	 * @param length The length of the CDI.
	 * @param riot_tcb TCB information for the RIoT Core context.
	 *
	 * @return 0 if the Device ID was successfully generated or an error code.
	 */
	int (*generate_device_id) (struct riot_core *riot, const uint8_t *cdi, size_t length,
		const struct x509_dice_tcbinfo *riot_tcb);

	/**
	 * Get the Certificate Signing Request for the Device ID.
	 *
	 * @param riot The RIoT Core instance to query.
	 * @param oid A custom OID to add to the Extended Key Usage extension of the CSR.  This is
	 * optional and can be set to null.
	 * @param csr Output for the CSR data.  This will be DER encoded in a dynamically allocated
	 * buffer.  It is the caller's responsibility to free the buffer.
	 * @param length Output for the length of the CSR data.
	 *
	 * @return 0 if the CSR was successfully retrieved or an error code.
	 */
	int (*get_device_id_csr) (struct riot_core *riot, const char *oid, uint8_t **csr,
		size_t *length);

	/**
	 * Get the X.509 certificate for the Device ID.  This certificate will be self-signed.
	 *
	 * @param riot The RIoT Core instance to query.
	 * @param device_id Output for the certificate data.  This will be DER encoded in a dynamically
	 * allocated buffer.  It is the caller's responsibility to free the buffer.
	 * @param length Output for the length of the certificate data.
	 *
	 * @return 0 if the Device ID certificate was successfully retrieved or an error code.
	 */
	int (*get_device_id_cert) (struct riot_core *riot, uint8_t **device_id, size_t *length);

	/**
	 * Generate the Alias key from the Firmware ID.  The Device ID must have already been
	 * generated.
	 *
	 * @param riot The RIoT Core instance.
	 * @param alias_tcb TCB information for the Alias context.
	 *
	 * @return 0 if the Alias Key was successfully generated or an error code.
	 */
	int (*generate_alias_key) (struct riot_core *riot, const struct x509_dice_tcbinfo *alias_tcb);

	/**
	 * Get the Alias private key.
	 *
	 * @param riot The RIoT Core instance to query.
	 * @param key Output for the private key.  This will be DER encoded in a dynamically allocated
	 * buffer.  It is the caller's responsibility to free the buffer.
	 * @param length The length of the key data.
	 *
	 * @return 0 if the Alias private key was successfully retrieved or an error code.
	 */
	int (*get_alias_key) (struct riot_core *riot, uint8_t **key, size_t *length);

	/**
	 * Get the X.509 certificate for the Alias key.  This certificate will be signed by the Device
	 * ID.
	 *
	 * @param riot The RIoT Core instance to query.
	 * @param alias_key Output for the certificate data.  This will be DER encoded in a dynamically
	 * allocated buffer.  It is the caller's responsibility to free the buffer.
	 * @param length Output for the length of the certificate data.
	 *
	 * @return 0 if the Alias key certificate was successfully retrieved or an error code.
	 */
	int (*get_alias_key_cert) (struct riot_core *riot, uint8_t **alias_key, size_t *length);
};


#define	RIOT_CORE_ERROR(code)		ROT_ERROR (ROT_MODULE_RIOT_CORE, code)

/**
 * Error codes that can be generated by RIoT Core.
 */
enum {
	RIOT_CORE_INVALID_ARGUMENT = RIOT_CORE_ERROR (0x00),	/**< Input parameter is null or not valid. */
	RIOT_CORE_NO_MEMORY = RIOT_CORE_ERROR (0x01),			/**< Memory allocation failed. */
	RIOT_CORE_NO_DEVICE_ID = RIOT_CORE_ERROR (0x02),		/**< No Device ID has been generated. */
	RIOT_CORE_NO_ALIAS_KEY = RIOT_CORE_ERROR (0x03),		/**< No Alias Key has been generated. */
	RIOT_CORE_BAD_FWID_LENGTH = RIOT_CORE_ERROR (0x04),		/**< The FWID is not the right length. */
};


#endif /* RIOT_CORE_H_ */
